package Game5;

import java.io.*;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Socket;
import java.net.SocketException;

public class TankClient {
    GamePanel gp;
    private static int UDP_PORT_START=2226;
    private int udpPort;
    DatagramSocket ds=null;
    public  TankClient(GamePanel gp) {
        this.udpPort=UDP_PORT_START++;
        this.gp=gp;
        try {
            ds=new DatagramSocket(udpPort);
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }
    public void connected(String IP,int port) {
        Socket s=null;
        try {
            s=new Socket(IP,port);
            DataOutputStream dos=new DataOutputStream(s.getOutputStream());
            dos.writeInt(udpPort);
            DataInputStream dis=new DataInputStream(s.getInputStream());
            int id=dis.readInt();
            gp.playerOne.id=id;
            System.out.println("Connected to server! and server give me a ID:" + id);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(s!=null) {
                    s.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //每次完成连接后，Client端都会传输给Server端坦克新诞生的消息，
        TankNewMsg msg=new TankNewMsg(gp.playerOne);
        send(msg);
        new Thread(new UDPRecvThread()).start();
    }

    //send方法单独包装，完成信息的传输
    //此处体现多态的好处，不同类别的消息去实现同一个接口，调用send方法时发生向上转型，通过多态来实现不同类别方法的传输
    public void send(Msg msg) {
        msg.send(ds,"127.0.0.1", TankServer.UDP_PORT);
    }
    //Client端接受信息线程，接受从Server端发送过来的UDP包
    private class UDPRecvThread implements Runnable {
        //把从Server端传过来的包读取到数组中
        byte[] buf=new byte[1024];
        @Override
        public void run() {
            while (ds!=null) {
                DatagramPacket dp=new DatagramPacket(buf,0,buf.length);
                try {
                    ds.receive(dp);
                    parse(dp);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        //拆包方法
        private void parse(DatagramPacket dp) {
            ByteArrayInputStream bais=new ByteArrayInputStream(buf,0,dp.getLength());
            DataInputStream dis=new DataInputStream(bais);
            int msgType=0;
            try {
                msgType= dis.readInt();
            } catch (IOException e) {
                e.printStackTrace();
            }
            Msg msg=null;
            switch(msgType) {
                case Msg.TANK_NEW_MSG:
                    msg=new TankNewMsg(TankClient.this.gp);//内部类中访问封装类的对象
                    //实例化新增坦克信息，让其在新增信息类中完成拆包
                    msg.parse(dis);
                    break;
                case Msg.TANK_MOVE_MSG:
                    msg=new TankMoveMsg(TankClient.this.gp);
                    msg.parse(dis);
                    break;
            }
        }
    }


}
